home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d971.lha / Yak / Source / handler.c < prev    next >
C/C++ Source or Header  |  1993-12-21  |  14KB  |  566 lines

  1. /*
  2.  * handler.c
  3.  *
  4.  * Routines to set up handler.
  5.  * Part of Yak.
  6.  *
  7.  * Martin W. Scott, 9/92.
  8.  */
  9. #include <exec/types.h>
  10. #include <exec/exec.h>
  11. #include <hardware/custom.h>
  12. #include <hardware/dmabits.h>
  13. #include <devices/console.h>
  14. #include <devices/input.h>
  15. #include <devices/inputevent.h>
  16. #include <libraries/commodities.h>
  17. #include <graphics/gfxbase.h>
  18. #include <graphics/gfxmacros.h>
  19. #include <graphics/displayinfo.h>
  20. #include <intuition/intuition.h>
  21. #include <intuition/intuitionbase.h>
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24. #include <proto/layers.h>
  25. #include <proto/graphics.h>
  26. #include <proto/intuition.h>
  27. #include <proto/commodities.h>
  28. #include <string.h>
  29.  
  30. #include "yak.h"
  31. #include "beep.h"
  32.  
  33.  
  34. static void __inline TurnMouseOn (void);
  35. static void __inline TurnMouseOff (void);
  36. static void __regargs IntuiOp (void (*routine) (APTR), APTR parameter);
  37. static void __regargs PopToFront (struct Window *win);
  38. static struct Window *WindowUnderMouse (void);
  39. static BOOL __regargs StrGadgetActive (struct Window *w);
  40.  
  41. extern struct Custom __far custom;
  42.  
  43. #define REBLANKCOUNT    10    /* how long to wait to reblank mouse */
  44.  
  45. void (*intui_routine) (APTR);    /* for intui_op's */
  46. APTR intui_parameter;
  47. CxObj *clickobj;
  48. ULONG clicksigflag, intuiopsigflag;
  49. static BYTE clicksigbit, intuiopsigbit = -1;
  50. static struct Task *thistask;
  51. static BOOL misspop;
  52.  
  53.  
  54. /* for screen click-to-back */
  55. void __stdargs
  56. MyScreenToBack (struct Screen *scr)
  57. {
  58.   struct Screen *ns = scr->NextScreen;
  59.   struct Window *win;
  60.  
  61.   if (!ns)
  62.       ns = IntuitionBase->FirstScreen;
  63.  
  64.   if (ns != scr)
  65.   {
  66.       ScreenToBack (scr);
  67.       if (scractivate && ns)
  68.       {
  69.           win = WindowUnderMouse();
  70.           if (win)
  71.               ActivateWindow (win);
  72.           else 
  73.               if (ns->FirstWindow)
  74.                   ActivateWindow (ns->FirstWindow);
  75.       }
  76.   }
  77. }
  78.  
  79.  
  80. /* Stub for Intuition routines - passes request on to main task.
  81.  * DO NOT CALL WHILE FORBID()ING!
  82.  
  83.  * Thanks to Eddy Carroll for this.
  84.  */
  85.  
  86. #define WTB(win)    IntuiOp(WindowToBack, win)
  87. #define WTF(win)    IntuiOp(WindowToFront, win)
  88. #define WACT(win)    IntuiOp((void (*)(APTR))ActivateWindow, win)
  89. #define STB(scr)    IntuiOp(MyScreenToBack, scr)
  90. #define STF(scr)    IntuiOp(ScreenToFront, scr)
  91.  
  92. static void __regargs
  93. IntuiOp (void (*routine) (APTR), APTR parameter)
  94. {
  95.   BYTE oldpri = SetTaskPri (thistask, 21);
  96.  
  97.   intui_routine = routine;
  98.   intui_parameter = parameter;
  99.   Signal (thistask, intuiopsigflag);
  100.   SetTaskPri (thistask, oldpri);
  101. }
  102.  
  103. /* pattern-matching on screen/window titles */
  104. #define IsXXXScreen(scr, pat)    (scr && (!scr->Title || MatchPattern(pat, scr->Title)))
  105. #define IsClickScreen(scr)    IsXXXScreen(scr, clickscrpat)
  106. #define IsAutoScreen(scr)    IsXXXScreen(scr, autoscrpat)
  107. #define IsXXXWindow(win, pat)    (!win->Title || MatchPattern(pat, win->Title))
  108. #define IsPopWindow(win)    IsXXXWindow(win,popwinpat)
  109. #define IsClickWindow(win)    IsXXXWindow(win,clickwinpat)
  110.  
  111. #define INTERRUPT void __interrupt __saveds
  112.  
  113. /* when is a window safe to bring to front and not already at front? */
  114. #define OkayToPop(win)    (!win->ReqCount && !(win->Flags & (WFLG_MENUSTATE|WFLG_BACKDROP)) \
  115.              && win->WLayer->ClipRect && win->WLayer->ClipRect->Next)
  116.  
  117.  
  118. /* WindowToFront only if no requester, not backdrop, not already front... */
  119. static void __regargs
  120. PopToFront (struct Window *win)
  121. {
  122.   /* want to avoid popping immediately after mousebutton/keyboard */
  123.   if (misspop)
  124.     misspop = FALSE;
  125.   else if (OkayToPop (win))
  126.     {
  127.       /* Does it pass pattern? */
  128.       if (IsPopWindow (win))
  129.           WTF (win);
  130.     }
  131. }
  132.  
  133. /* modified from DMouse */
  134. /* expects multitasking to be Forbid()en */
  135.  
  136. static struct Screen *mousescr;    /* the screen under the mouse */
  137.  
  138.  
  139. void
  140. ScreenUnderMouse( void )
  141. {
  142.   for (mousescr = IntuitionBase->FirstScreen ; 
  143.        mousescr && mousescr->TopEdge > 0 && mousescr->MouseY < 0; 
  144.        mousescr = mousescr->NextScreen);
  145. }
  146.  
  147.  
  148. static struct Window *
  149. WindowUnderMouse ( void )
  150. {
  151.   struct Layer *layer = NULL;
  152.  
  153.   for (mousescr = IntuitionBase->FirstScreen ; 
  154.        mousescr && mousescr->TopEdge > 0 && mousescr->MouseY < 0; 
  155.        mousescr = mousescr->NextScreen);
  156.   
  157.   if (mousescr)
  158.       layer = WhichLayer(&mousescr->LayerInfo, mousescr->MouseX, mousescr->MouseY);
  159.  
  160.   return (layer ? (struct Window *) layer->Window : NULL);
  161. }
  162.  
  163.  
  164. /* does active window have an active string gadget? */
  165. static BOOL __regargs
  166. StrGadgetActive (struct Window *w)
  167. {
  168.   struct Gadget *g = w->FirstGadget;
  169.  
  170.   for (; g; g = g->NextGadget)
  171.     if ((g->GadgetType & STRGADGET) && (g->Flags & GFLG_SELECTED))
  172.       return TRUE;
  173.   return FALSE;
  174. }
  175.  
  176. /* activate window under mouse */
  177. /* context sensitive; why tells routine how to behave */
  178. /* can be AUTO, KEY, SCREEN, RMBACT */
  179. #define AW    IntuitionBase->ActiveWindow
  180. #define AWS    IntuitionBase->ActiveWindow->WScreen
  181. #define FS    IntuitionBase->FirstScreen
  182. #define FSW    IntuitionBase->FirstScreen->FirstWindow
  183. void __regargs
  184. ActivateMouseWindow (BYTE why)
  185. {
  186.   struct Window *win;
  187.   BOOL forbidden = TRUE;
  188.  
  189.   Forbid ();
  190.  
  191.   if (win = WindowUnderMouse ())    /* window exists to activate */
  192.   {
  193.       /* either window is not active or auto-activating - need to pop? */
  194.       
  195.       if (win->Flags & WFLG_WINDOWACTIVE)    /* already active - needs popped? */
  196.       {
  197.           if (why == AUTO && autopop && IsAutoScreen (win->WScreen))
  198.           {
  199.               Permit (), forbidden = FALSE;
  200.               PopToFront (win);
  201.           }
  202.       }
  203.       else if (why != AUTO || IsAutoScreen (win->WScreen))
  204.       {
  205.           /* window is not active, should we try to activate it? */
  206.           
  207.           /* AW is IntuitionBase->ActiveWindow */
  208.           if (!AW ||
  209.               !(AW->Flags & WFLG_MENUSTATE) &&    /* not showing menus */
  210.               !(why == KEY && StrGadgetActive (AW)))    /* no str gad active */
  211.           {
  212.               /* finally... */
  213.               Permit (), forbidden = FALSE;
  214.               
  215.               /* do autopop? */
  216.               if (why == AUTO && autopop)
  217.                   PopToFront (win);
  218.               
  219.               if (why == KEY)
  220.                   ActivateWindow (win);    /* need this to avoid losing keys */
  221.               else
  222.                   WACT (win);    /* ...activate window */
  223.           }
  224.       }
  225.   }
  226.   else
  227.     /* no window under mouse... */
  228.     {
  229.       if (mousescr && mousescr->FirstWindow &&
  230.       ((why == SCREEN) || (why == RMBACT && AW && AWS != mousescr)))
  231.     {
  232.       Permit (), forbidden = FALSE;
  233.       WACT (mousescr->FirstWindow);        /* ...activate window */
  234.     }
  235.     }
  236.   if (forbidden)
  237.     Permit ();
  238. }
  239.  
  240. static UWORD __chip posctldata[4];
  241. static struct SimpleSprite simplesprite =
  242. {posctldata, 0, 0, 0, 0};
  243. static BOOL mouseoff;        /* is mouse off? (MB_SPRITES only) */
  244.  
  245. static void __inline
  246. TurnMouseOn ()            /* restore mouse-pointer */
  247. {
  248.   if (mouseblank == MB_SPRITES)    /* really dirty blanking */
  249.     {                /* but guaranteed to work... */
  250.       if (mouseoff)
  251.     {
  252.       Forbid ();
  253.       WaitTOF ();
  254.       ON_SPRITE;
  255.       Permit ();
  256.     }
  257.     }
  258.   /* else using FreeSprite solution - unblanks when needed */
  259.   mouseoff = FALSE;
  260. }
  261.  
  262. static void __inline
  263. TurnMouseOff ()            /* blank mouse-pointer */
  264. {
  265.   if (!mouseoff)        /* no point in turning it off twice... */
  266.     {
  267.       Forbid ();
  268.  
  269.       if (mouseblank == MB_SPRITES)
  270.     {
  271.       WaitTOF ();
  272.       OFF_SPRITE;
  273.       custom.spr[0].dataa = custom.spr[0].datab = 0;
  274.     }
  275.       else
  276.     {
  277.       FreeSprite (0);
  278.       GetSprite (&simplesprite, 0);
  279.     }
  280.  
  281.       Permit ();
  282.  
  283.       mouseoff = TRUE;
  284.     }
  285. }
  286.  
  287. static BOOL blanked;
  288. static struct Screen *blankscr;
  289.  
  290. /* blank display, by putting up a black screen */
  291. /* this screen's displaymode is cloned from front screen */
  292. void
  293. BlankScreen ()
  294. {
  295.     ULONG modeid = INVALID_ID;
  296.     
  297.     if (blankscr)
  298.         ScreenToFront (blankscr);
  299.     else
  300.     {
  301.         Forbid ();
  302.         if (FS)
  303.             modeid = GetVPModeID (&(FS->ViewPort));
  304.         Permit ();
  305.         if (modeid == INVALID_ID)
  306.             modeid = LORES_KEY;
  307.         
  308.         if (blankscr = OpenScreenTags (NULL, SA_Depth, 1,
  309.                                        SA_Quiet, TRUE,
  310.                                        SA_Behind, TRUE,
  311.                                        SA_DisplayID, modeid,
  312.                                        TAG_DONE))
  313.         {
  314.             SetRGB4 (&blankscr->ViewPort, 0, 0, 0, 0);
  315.             ScreenToFront (blankscr);
  316.             blanked = TRUE;
  317.         }
  318.     }
  319.     OFF_SPRITE;
  320.     custom.spr[0].dataa = custom.spr[0].datab = 0;
  321. }
  322.  
  323. /* unblank display, i.e. close our screen */
  324. void
  325. UnBlankScreen ()
  326. {
  327.   if (blankscr)
  328.       CloseScreen (blankscr);
  329.   blankscr = NULL;
  330.   blanked = FALSE;
  331.   ON_SPRITE;
  332. }
  333.  
  334. #define ALL_BUTTONS    (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)
  335. #define KEY_QUAL    (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT \
  336.             |IEQUALIFIER_CONTROL \
  337.             |IEQUALIFIER_LALT|IEQUALIFIER_RALT \
  338.             |IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)
  339. #define ALL_QUALS    (ALL_BUTTONS|KEY_QUAL)
  340.  
  341. /* the input handler itself */
  342. INTERRUPT
  343. Handler (CxMsg * CxMsg, CxObj * CO)
  344. {
  345.     static struct timeval lastclick; /* last left-button click */
  346.     static WORD apcount;        /* timer events since last mousemove */
  347.     struct InputEvent *ev;
  348.     
  349.     ev = (struct InputEvent *) CxMsgData (CxMsg);
  350.     
  351.     if (ev->ie_Class == IECLASS_TIMER)
  352.     {
  353.         /*** AUTO-ACTIVATE/POP, SCREENBLANK, MOUSEBLANK ***/
  354.         if (!(ev->ie_Qualifier & ALL_QUALS) && autopoint && !apcount--)
  355.         {
  356.             ActivateMouseWindow (AUTO);
  357.         }
  358.         
  359.         if (blanktimeout && !--blankcount) /* blank screen? */
  360.         {
  361.             BlankScreen ();
  362.             blankcount = blanktimeout; /* reset counter */
  363.         }                        /* in case sceen opens on top */
  364.         
  365.         if (mouseblank && !--mblankcount) /* blank mouse? */
  366.         {
  367.             mouseoff = FALSE;    /* force reblank */
  368.             TurnMouseOff ();
  369.             /* in case someone else turns it on, reset counter */
  370.             mblankcount = REBLANKCOUNT;
  371.         }
  372.     }
  373.     else 
  374.         if ((ev->ie_Class == IECLASS_RAWKEY) && !(ev->ie_Code & IECODE_UP_PREFIX))
  375.         {
  376.             /*** MOUSEBLANK, KEYACTIVATE, KEYCLICK ***/
  377.             
  378.             blankcount = blanktimeout; /* reset blanking countdown */
  379.             if (blanked)        /* turn off screen-blanking */
  380.                 UnBlankScreen ();
  381.             
  382.             if (mouseblank)
  383.                 if (ev->ie_Qualifier & IEQUALIFIER_LCOMMAND)
  384.                 {
  385.                     /* this allows use of keyboard to move mouse */
  386.                     mblankcount = mblanktimeout;
  387.                     TurnMouseOn ();
  388.                 }
  389.                 else
  390.                     TurnMouseOff (); /* blank the mouse */
  391.             
  392.             if (click_volume)
  393.                 Signal (thistask, clicksigflag);
  394.             
  395.             if (keyactivate)    /* perform key-activate */
  396.                 ActivateMouseWindow (KEY);
  397.         }
  398.         else if (ev->ie_Class == IECLASS_RAWMOUSE)
  399.         {
  400.             /*** CLICKTOFRONT/BACK, AUTOACTIVATE ***/
  401.             
  402.             /* restore screen/mouse pointer */
  403.             blankcount = blanktimeout; /* reset blanking countdowns */
  404.             mblankcount = mblanktimeout;
  405.             if (blanked)        /* turn off screen-blanking */
  406.                 UnBlankScreen ();
  407.             if (mouseoff)
  408.                 TurnMouseOn ();    /* not needed for MB_COPPER */
  409.             
  410.             /* window/screen cycling... */
  411.             /* maybe should check for depth gadgets? nah... */
  412.             if (!(ev->ie_Qualifier & KEY_QUAL))
  413.             {
  414.                 if (!(ev->ie_Qualifier & ALL_BUTTONS))
  415.                 {
  416.                     apcount = autopoint_delay; /* reset auto-activate count */
  417.                 }
  418.                 else
  419.                     /* a button - check out clicktofront etc. */
  420.                 {
  421.                     /* mustn't be Forbid()en when calling window op */
  422.                     BOOL forbidden = TRUE;
  423.  
  424.                     Forbid ();
  425.  
  426.                     misspop = TRUE;
  427.                     apcount = -1; /* button - wait for move */
  428.  
  429.                     if (clicktofront && ev->ie_Code == IECODE_LBUTTON)
  430.                     {
  431.                         if (DoubleClick (lastclick.tv_secs,
  432.                                          lastclick.tv_micro,
  433.                                          ev->ie_TimeStamp.tv_secs,
  434.                                          ev->ie_TimeStamp.tv_micro))
  435.                         {
  436.                             
  437.                             struct Window *win = WindowUnderMouse ();
  438.  
  439.                             if (win)
  440.                             {
  441.                                 Permit (), forbidden = FALSE;
  442.                                 mousescr = win->WScreen;
  443.                                 
  444.                                 if (IsClickScreen ( mousescr ))
  445.                                 {
  446.                                     if (!(win->Flags & WFLG_BACKDROP) 
  447.                                         && IsClickWindow (win) && OkayToPop (win))
  448.                                     {
  449.                                         WTF (win); /* musn't be Forbid()en here */
  450.                                     }
  451.                                     else 
  452.                                         if (screencycle)
  453.                                         {
  454.                                             STF (mousescr); /* musn't be Forbid()en here */
  455.                                         }
  456.                                 }
  457.                             }
  458.                             else 
  459.                             {
  460.                                 ScreenUnderMouse();
  461.                                 Permit (), forbidden = FALSE;
  462.                                 if (IsClickScreen ( mousescr ) && screencycle)
  463.                                 {
  464.                                     STF (mousescr); /* musn't be Forbid()en here */
  465.                                 }
  466.                             }
  467.                             lastclick.tv_secs = 0;
  468.                             lastclick.tv_micro = 0;
  469.                         }
  470.                         else
  471.                         {
  472.                             lastclick.tv_secs = ev->ie_TimeStamp.tv_secs;
  473.                             lastclick.tv_micro = ev->ie_TimeStamp.tv_micro;
  474.                         }
  475.                     }
  476.                     else 
  477.                         if (ev->ie_Code == IECODE_RBUTTON && 
  478.                             (ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON))
  479.                         {
  480.                             struct Window *win = WindowUnderMouse ();
  481.  
  482.                             if (win)
  483.                             {
  484.                                 Permit (), forbidden = FALSE;
  485.                                 mousescr = win->WScreen;
  486.                                 if (IsClickScreen ( mousescr ))
  487.                                 {
  488.                                     if (!(win->Flags & WFLG_BACKDROP) 
  489.                                         && (win->NextWindow || win->WScreen->FirstWindow != win))
  490.                                     {
  491.                                         WTB(win); /* musn't be Forbid()en here */
  492.                                     }
  493.                                     else 
  494.                                         if (screencycle)
  495.                                         {
  496.                                             STB (mousescr); /* musn't be Forbid()en here */
  497.                                         }
  498.                                 }    
  499.                             }
  500.                             else 
  501.                             {
  502.                                 ScreenUnderMouse();
  503.                                 Permit (), forbidden = FALSE;
  504.                                 if (IsClickScreen ( mousescr ) && screencycle)
  505.                                 {
  506.                                     ev->ie_Class = IECLASS_NULL;
  507.                                     STB (mousescr);
  508.                                 }
  509.                             }
  510.                         }
  511.                         else 
  512.                             if ((rmbactivate && (ev->ie_Code == IECODE_RBUTTON)) || 
  513.                                 (mmbactivate && (ev->ie_Code == IECODE_MBUTTON)))
  514.                             {
  515.                                 Permit (), forbidden = FALSE;
  516.                                 ActivateMouseWindow (RMBACT);
  517.                             }
  518.                         if (forbidden)
  519.                             Permit ();
  520.                     }
  521.                 }
  522.         }
  523.         else 
  524.             if (ev->ie_Class == IECLASS_DISKINSERTED)
  525.             {
  526.                 blankcount = blanktimeout; /* reset blanking countdown */
  527.                 if (blanked)        /* turn off screen-blanking */
  528.                     UnBlankScreen ();
  529.             }
  530. }
  531.  
  532. /* close resources allocated for handler */
  533. void
  534. EndHandler ()
  535. {
  536.   if (clickobj)
  537.     DeleteCxObj (clickobj);
  538.   FreeAudio ();
  539.   if (intuiopsigbit != -1)
  540.     FreeSignal (intuiopsigbit);
  541.   if (clicksigbit != -1)
  542.     FreeSignal (clicksigbit);
  543.   UnBlankScreen ();
  544.   TurnMouseOn ();
  545. }
  546.  
  547. /* open resources needed for handler */
  548. BOOL
  549. InitHandler ()
  550. {
  551.   if (((clicksigbit = AllocSignal (-1)) != -1) &&
  552.       ((intuiopsigbit = AllocSignal (-1)) != -1) &&
  553.       AllocAudio ())
  554.     {
  555.       thistask = FindTask (NULL);    /* initialize liason structure */
  556.       clicksigflag = 1 << clicksigbit;
  557.       intuiopsigflag = 1 << intuiopsigbit;
  558.  
  559.       clickobj = CxCustom (Handler, 0L);
  560.       AttachCxObj (broker, clickobj);
  561.       return TRUE;
  562.     }
  563.   EndHandler ();
  564.   return FALSE;
  565. }
  566.